﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using HRProject.Code.DTO;
using System.Collections.Generic;
using HRProject.Code.Common;
using System.Drawing;

namespace HRProject.Code.DAO
{
    public class TaskDAO : BaseDAO
    {
        public TaskDAO()
            : base ()
        {
        }

        public List<BLTask> findForMonthDisplay(Guid userId, int year, int month)
        {
            DateTime firstDateOfMonth = new DateTime(year, month, 1);
            while (!firstDateOfMonth.DayOfWeek.Equals(DayOfWeek.Monday))
            {
                firstDateOfMonth = firstDateOfMonth.AddDays(-1);
            }
            DateTime lastDateOfMonth = new DateTime(year, month, DateTime.DaysInMonth(year,month));
            while (!lastDateOfMonth.DayOfWeek.Equals(DayOfWeek.Sunday))
            {
                lastDateOfMonth = lastDateOfMonth.AddDays(1);
            }

            List<DateTime> endTimesOfWeeks = new List<DateTime>();
            DateTime temp = firstDateOfMonth.AddDays(7);
            while (temp <= lastDateOfMonth)
            {
                endTimesOfWeeks.Add(temp);
                temp = temp.AddDays(7);
            }

            BLTaskFilter filter = new BLTaskFilter();
            filter.Id = Guid.Empty;
            filter.Name = string.Empty;
            filter.Type = new BLTaskType();
            filter.Type.Id = Guid.Empty;
            filter.EstimateFinishDateDown = firstDateOfMonth;
            filter.EstimateFinishDateUp = lastDateOfMonth;
            filter.InChargeUserId = (Guid)userId;
            List<BLTask> pre = search(filter);

            filter.EstimateFinishDateDown = firstDateOfMonth;
            filter.EstimateFinishDateUp = Constant.DefaultMaxDate;
            filter.EstimateStartDateDown = firstDateOfMonth;
            filter.EstimateStartDateUp = lastDateOfMonth;
            List<BLTask> suf = search(filter);

            List<BLTask> result = new List<BLTask>();
            int color = 105200;//increase 10550
            for (int i = 0; i < pre.Count; i++)
            {
                if (pre[i].EstimateStartDate < firstDateOfMonth)
                {
                    pre[i].EstimateStartDate = firstDateOfMonth;
                }
                color += 10550;
                pre[i].DisplayColor = Color.FromArgb(color);
                List<BLTask> splits = new List<BLTask>();
                splits.Add(pre[i]);
                while(!isSameWeek(splits[splits.Count-1].EstimateStartDate,splits[splits.Count-1].EstimateFinishDate))
                {
                    DateTime lastTimeOfWeek = getLastTimeOfWeek(splits[splits.Count - 1].EstimateStartDate);
                    BLTask more = new BLTask();
                    more.Id = splits[splits.Count - 1].Id;
                    more.Name = splits[splits.Count - 1].Name;
                    more.EstimateStartDate = lastTimeOfWeek.AddSeconds(1);
                    more.EstimateFinishDate = splits[splits.Count - 1].EstimateFinishDate;
                    more.DisplayColor = Color.FromArgb(color);
                    splits[splits.Count - 1].EstimateFinishDate = lastTimeOfWeek;
                    splits.Add(more);
                }
                foreach (BLTask s in splits)
                {
                    result.Add(s);
                }
            }

            for (int i = 0; i < suf.Count; i++)
            {
                bool already = false;
                for (int j = 0; j < result.Count; j++)
                {
                    if (result[j].Id.Equals(suf[i].Id))
                    {
                        already = true;
                        break;
                    }
                }
                if (!already)
                {
                    if (suf[i].EstimateFinishDate > lastDateOfMonth)
                    {
                        suf[i].EstimateFinishDate = lastDateOfMonth.AddDays(0.99);
                    }
                    color += 10550;
                    suf[i].DisplayColor = Color.FromArgb(color);
                    List<BLTask> splits = new List<BLTask>();
                    splits.Add(suf[i]);
                    while (!isSameWeek(splits[splits.Count - 1].EstimateStartDate, splits[splits.Count - 1].EstimateFinishDate))
                    {
                        DateTime lastTimeOfWeek = getLastTimeOfWeek(splits[splits.Count - 1].EstimateStartDate);
                        BLTask more = new BLTask();
                        more.Id = splits[splits.Count - 1].Id;
                        more.Name = splits[splits.Count - 1].Name;
                        more.EstimateStartDate = lastTimeOfWeek.AddSeconds(1);
                        more.EstimateFinishDate = splits[splits.Count - 1].EstimateFinishDate;
                        more.DisplayColor = Color.FromArgb(color);
                        splits[splits.Count - 1].EstimateFinishDate = lastTimeOfWeek;
                        splits.Add(more);
                    }
                    foreach (BLTask s in splits)
                    {
                        result.Add(s);
                    }
                }
            }
            return result;
        }

        public bool isSameWeek(DateTime d1, DateTime d2)
        {
            DateTime small = d1;
            DateTime big = d2;
            if (d1 > d2)
            {
                small = d2;
                big = d1;
            }
            DateTime temp = small;
            while (!temp.DayOfWeek.Equals(DayOfWeek.Sunday))
            {
                temp = temp.AddDays(1);
            }
            temp = new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59, 99);
            return (big <= temp);
        }

        public DateTime getLastTimeOfWeek(DateTime d)
        {
            DateTime temp = d;
            while (!temp.DayOfWeek.Equals(DayOfWeek.Sunday))
            {
                temp = temp.AddDays(1);
            }
            return new DateTime(temp.Year, temp.Month, temp.Day, 23, 59, 59, 99);
        }

        public List<BLTask> search(BLTaskFilter filter)
        {
            List<BLTask> result = new List<BLTask>();
            List<BaseCondition> condition = new List<BaseCondition>();
            condition.Add(new BaseCondition("@id", filter.Id,ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", filter.Name,ParameterDirection.Input));
            condition.Add(new BaseCondition("@typeId", filter.Type.Id,ParameterDirection.Input));
            condition.Add(new BaseCondition("@inChargeUserId", filter.InChargeUserId, ParameterDirection.Input));
            if (filter.EstimateStartDateDown < Constant.DefaultMinDate || filter.EstimateStartDateDown > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDateDown", filter.EstimateStartDateDown, ParameterDirection.Input));
            }
            if (filter.EstimateStartDateUp < Constant.DefaultMinDate || filter.EstimateStartDateUp > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDateUp", filter.EstimateStartDateUp, ParameterDirection.Input));
            }

            if (filter.EstimateFinishDateDown < Constant.DefaultMinDate || filter.EstimateFinishDateDown > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDateDown", filter.EstimateFinishDateDown, ParameterDirection.Input));
            }
            if (filter.EstimateFinishDateUp < Constant.DefaultMinDate || filter.EstimateFinishDateUp > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDateUp", filter.EstimateFinishDateUp, ParameterDirection.Input));
            }

            if (filter.RealStartDateDown < Constant.DefaultMinDate || filter.RealStartDateDown > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDateDown", filter.RealStartDateDown, ParameterDirection.Input));
            }
            if (filter.RealStartDateUp < Constant.DefaultMinDate || filter.RealStartDateUp > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDateUp", filter.RealStartDateUp, ParameterDirection.Input));
            }

            if (filter.RealFinishDateDown < Constant.DefaultMinDate || filter.RealFinishDateDown > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDateDown", filter.RealFinishDateDown, ParameterDirection.Input));
            }
            if (filter.RealFinishDateUp < Constant.DefaultMinDate || filter.RealFinishDateUp > Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDateUp", filter.RealFinishDateUp, ParameterDirection.Input));
            }
            DataTable data = select("usp_searchTasks", condition);
            for (int i = 0; i < data.Rows.Count; i++)
            {
                BLTask task = new BLTask();
                task.Id = (Guid)data.Rows[i]["TaskId"];
                task.Name = (string)data.Rows[i]["TaskName"];
                task.Description = (string)data.Rows[i]["Description"];
                task.EstimateStartDate = (DateTime)data.Rows[i]["EstimateStartDate"];
                task.EstimateFinishDate = (DateTime)data.Rows[i]["EstimateFinishDate"];
                task.RealStartDate = (DateTime)data.Rows[i]["RealStartDate"];
                task.RealFinishDate = (DateTime)data.Rows[i]["RealFinishDate"];
                task.Type = new BLTaskType();
                task.Type.Id = (Guid)data.Rows[i]["TaskTypeId"];
                task.Type.Name = (string)data.Rows[i]["TaskTypeName"];
                task.InChargeUserId = (Guid)data.Rows[i]["InChargeUserId"];
                task.DataSignature = (long)data.Rows[i]["DataSignature"];
                task.CreateDate = (DateTime)data.Rows[i]["CreateDate"];
                task.CreateUserId = (Guid)data.Rows[i]["CreateUserId"];
                task.UpdateDate = (DateTime)data.Rows[i]["UpdateDate"];
                task.UpdateUserId = (Guid)data.Rows[i]["UpdateUserId"];
                result.Add(task);
            }
            return result;
        }

        public List<BLTask> searchByUser(BLTaskFilter filter)
        {
            List<BLTask> result = new List<BLTask>();
            List<BaseCondition> condition = new List<BaseCondition>();
            condition.Add(new BaseCondition("@id", filter.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", filter.Name, ParameterDirection.Input));
            condition.Add(new BaseCondition("@typeId", filter.Type.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@inChargeUserId", filter.InChargeUserId, ParameterDirection.Input));
            if (filter.EstimateStartDateDown <= Constant.DefaultMinDate || filter.EstimateStartDateDown >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDateDown", filter.EstimateStartDateDown, ParameterDirection.Input));
            }
            if (filter.EstimateStartDateUp <= Constant.DefaultMinDate || filter.EstimateStartDateUp >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDateUp", filter.EstimateStartDateUp, ParameterDirection.Input));
            }

            if (filter.EstimateFinishDateDown <= Constant.DefaultMinDate || filter.EstimateFinishDateDown >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDateDown", filter.EstimateFinishDateDown, ParameterDirection.Input));
            }
            if (filter.EstimateFinishDateUp <= Constant.DefaultMinDate || filter.EstimateFinishDateUp >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDateUp", filter.EstimateFinishDateUp, ParameterDirection.Input));
            }

            if (filter.RealStartDateDown <= Constant.DefaultMinDate || filter.RealStartDateDown >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDateDown", filter.RealStartDateDown, ParameterDirection.Input));
            }
            if (filter.RealStartDateUp <= Constant.DefaultMinDate || filter.RealStartDateUp >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDateUp", filter.RealStartDateUp, ParameterDirection.Input));
            }

            if (filter.RealFinishDateDown <= Constant.DefaultMinDate || filter.RealFinishDateDown >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDateDown", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDateDown", filter.RealFinishDateDown, ParameterDirection.Input));
            }
            if (filter.RealFinishDateUp <= Constant.DefaultMinDate || filter.RealFinishDateUp >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDateUp", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDateUp", filter.RealFinishDateUp, ParameterDirection.Input));
            }
            DataTable data = select("usp_searchTasksOfUser", condition);
            for (int i = 0; i < data.Rows.Count; i++)
            {
                BLTask task = new BLTask();
                task.Id = (Guid)data.Rows[i]["TaskId"];
                task.Name = (string)data.Rows[i]["TaskName"];
                task.Description = (string)data.Rows[i]["Description"];
                task.EstimateStartDate = (DateTime)data.Rows[i]["EstimateStartDate"];
                task.EstimateFinishDate = (DateTime)data.Rows[i]["EstimateFinishDate"];
                task.RealStartDate = (DateTime)data.Rows[i]["RealStartDate"];
                task.RealFinishDate = (DateTime)data.Rows[i]["RealFinishDate"];
                task.InChargeUserId = (Guid)data.Rows[i]["InChargeUserId"];
                task.Type = new BLTaskType();
                task.Type.Id = (Guid)data.Rows[i]["TaskTypeId"];
                task.Type.Name = (string)data.Rows[i]["TaskTypeName"];
                task.DataSignature = (long)data.Rows[i]["DataSignature"];
                task.CreateDate = (DateTime)data.Rows[i]["CreateDate"];
                task.CreateUserId = (Guid)data.Rows[i]["CreateUserId"];
                task.UpdateDate = (DateTime)data.Rows[i]["UpdateDate"];
                task.UpdateUserId = (Guid)data.Rows[i]["UpdateUserId"];
                result.Add(task);
            }
            return result;
        }

        public int insert(BLTask task)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            int errorCode = 0;
            condition.Add(new BaseCondition("@id", Guid.NewGuid(), ParameterDirection.Input));
            condition.Add(new BaseCondition("@name",task.Name,ParameterDirection.Input));
            condition.Add(new BaseCondition("@description", task.Description, ParameterDirection.Input));
            condition.Add(new BaseCondition("@inChargeUserId", task.InChargeUserId, ParameterDirection.Input));
            if (task.EstimateStartDate <= Constant.DefaultMinDate || task.EstimateStartDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDate", task.EstimateStartDate, ParameterDirection.Input));
            }

            if (task.EstimateFinishDate <= Constant.DefaultMinDate || task.EstimateFinishDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDate", task.EstimateFinishDate, ParameterDirection.Input));
            }

            if (task.RealStartDate <= Constant.DefaultMinDate || task.RealStartDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDate", task.RealStartDate, ParameterDirection.Input));
            }

            if (task.RealFinishDate <= Constant.DefaultMinDate || task.RealFinishDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDate", task.RealFinishDate, ParameterDirection.Input));
            }
            condition.Add(new BaseCondition("@typeId", task.Type.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@createUserId", Membership.GetUser().ProviderUserKey.ToString(),ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature",task.DataSignature,ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode",errorCode,ParameterDirection.Output));
            int result = update("usp_addTask", condition);
            return result;
        }

        public int update(BLTask task)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            int errorCode = 0;
            condition.Add(new BaseCondition("@id", task.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@name", task.Name, ParameterDirection.Input));
            condition.Add(new BaseCondition("@description", task.Description, ParameterDirection.Input));
            condition.Add(new BaseCondition("@inChargeUserId", task.InChargeUserId, ParameterDirection.Input));
            if (task.EstimateStartDate <= Constant.DefaultMinDate || task.EstimateStartDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateStartDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateStartDate", task.EstimateStartDate, ParameterDirection.Input));
            }

            if (task.EstimateFinishDate <= Constant.DefaultMinDate || task.EstimateFinishDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@estimateFinishDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@estimateFinishDate", task.EstimateFinishDate, ParameterDirection.Input));
            }

            if (task.RealStartDate <= Constant.DefaultMinDate || task.RealStartDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realStartDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realStartDate", task.RealStartDate, ParameterDirection.Input));
            }

            if (task.RealFinishDate <= Constant.DefaultMinDate || task.RealFinishDate >= Constant.DefaultMaxDate)
            {
                condition.Add(new BaseCondition("@realFinishDate", null, ParameterDirection.Input));
            }
            else
            {
                condition.Add(new BaseCondition("@realFinishDate", task.RealFinishDate, ParameterDirection.Input));
            }
            condition.Add(new BaseCondition("@typeId", task.Type.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", Membership.GetUser().ProviderUserKey.ToString(), ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", task.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_updateTask", condition);
            return result;
        }

        public int delete(BLTask task)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            int errorCode = 0;
            condition.Add(new BaseCondition("@id", task.Id, ParameterDirection.Input));
            condition.Add(new BaseCondition("@updateUserId", Membership.GetUser().ProviderUserKey.ToString(), ParameterDirection.Input));
            condition.Add(new BaseCondition("@dataSignature", task.DataSignature, ParameterDirection.Input));
            condition.Add(new BaseCondition("@errorCode", errorCode, ParameterDirection.Output));
            int result = update("usp_deleteTask", condition);
            return result;
        }

        public int countUnfinishedTasks(Guid userId)
        {
            List<BaseCondition> condition = new List<BaseCondition>();
            condition.Add(new BaseCondition("@userId", userId, ParameterDirection.Input));
            DataTable data = select("usp_countUnfinishedTasks", condition);
            int result = 0;
            if (data.Rows.Count>0)
            {
                result = (int)data.Rows[0]["NumberOfTask"];
            }
            return result;
        }

        public List<BLTaskStatistics> makeStatistics(Guid userId, int year, out int maxInEachRecord)
        {
            List<BLTaskStatistics> result = new List<BLTaskStatistics>();
            maxInEachRecord = 0;
            for (int i = 1; i <= 12; i++)
            {
                List<BaseCondition> condition = new List<BaseCondition>();
                condition.Add(new BaseCondition("@userId", userId, ParameterDirection.Input));
                condition.Add(new BaseCondition("@from", new DateTime(year, i, 1), ParameterDirection.Input));
                condition.Add(new BaseCondition("@to", new DateTime(year, i, DateTime.DaysInMonth(year, i)), ParameterDirection.Input));
                DataTable data = select("usp_MakeStatisticsOfTasksForUser", condition);
                BLTaskStatistics statistics = new BLTaskStatistics();
                statistics.Finished = 0;
                statistics.Unfinished = 0;
                if (data.Rows.Count > 0)
                {
                    statistics.Finished = (int)data.Rows[0]["Finished"];
                    statistics.Unfinished = (int)data.Rows[0]["Unfinished"];
                    int total = statistics.Finished + statistics.Unfinished;
                    if (total > maxInEachRecord)
                        maxInEachRecord = total;
                }
                result.Add(statistics);
            }
            return result;
        }
    }
}
